#ifndef __FRAME_MACRO__
#define __FRAME_MACRO__

#include "macro/common_macro.h"

namespace frame {

#define ONCE_PER_FRAME(judger, type)                                               \
  private:                                                                         \
    unsigned int _last_##judger##_check_frame{0};                                  \
    type         _last_##judger##_check_result;                                    \
                                                                                   \
  public:                                                                          \
    type& judger() {                                                               \
        if (_last_##judger##_check_frame != frame_number_ or frame_number_ == 0) { \
            _last_##judger##_check_frame  = frame_number_;                         \
            _last_##judger##_check_result = _##judger();                           \
        }                                                                          \
        return _last_##judger##_check_result;                                      \
    }

#define ONCE_PER_FRAME_TUPLE(judger, ...)                                          \
  private:                                                                         \
    unsigned int            _last_##judger##_check_frame{0};                       \
    std::tuple<__VA_ARGS__> _last_##judger##_check_result;                         \
                                                                                   \
  public:                                                                          \
    std::tuple<__VA_ARGS__>& judger() {                                            \
        if (_last_##judger##_check_frame != frame_number_ or frame_number_ == 0) { \
            _last_##judger##_check_frame  = frame_number_;                         \
            _last_##judger##_check_result = _##judger();                           \
        }                                                                          \
        return _last_##judger##_check_result;                                      \
    }

#define DECLARE_FRAME_NUMBER        \
  private:                          \
    unsigned int frame_number_ = 0; \
                                    \
  public:                           \
    void UpdateOnce() {             \
        ++frame_number_;            \
    }

} // namespace frame

#define Frame frame::_Frame::GetInstance()

#endif // __FRAME_MACRO__
